#include <QtCore/QFile>
#include <QtCore/QTextStream>
#include <QtCore/QStringList>
#include <iostream>
#include "Translate.h"
#include "Log.h"

QVector<Dictionary> Translator::m_dic;
int Translator::m_lastID = 1;

QString Tags::join(bool keepTag) const {
  QString s;
  Q_FOREACH(const Tag& tag, *this)  {
    if (keepTag || tag.second) s += tag.first+" ";
  }
  return s;
}

void Dictionary::load(const QString& fName)
{
	QFile file(fName);
	file.open(QIODevice::ReadOnly);
	if (!file.isOpen()) {
		Log::m_log << "Cannot open " << fName << endl;
		return;
	}
	QTextStream in(&file);
  in.setCodec("UTF-8");
	while (!in.atEnd()) {
		QString line = in.readLine().trimmed();
		if (line.isEmpty()) continue;
		int p = line.indexOf("=");
		if (p == -1) continue;
		QString from = line.left(p);
		QStringList tmpList = line.mid(p+1).split("/"), toList;
		for (int i = 0; i < tmpList.size(); i++) {
			QString to = tmpList[i].trimmed(); //.toLower();
			if (!to.isEmpty()) 
				toList << to;
		}
		if (!toList.isEmpty()) (*this)[from] << toList;
	}
	Log::m_log << fName << " read: " << this->size() << endl;
}

void Dictionary::save(const QString& fName)
{
  QFile file(fName);
  file.open(QIODevice::WriteOnly);
  QTextStream out(&file);
  out.setCodec("UTF-8");
  Log::m_log << "saving dictionary: " << size() << endl;
  for (iterator itr = begin(); itr != end(); itr++) {
    const QString& from = itr.key();
    const QStringList& toList = itr.value();
    out << from << "=";
    if (!toList.isEmpty()) out << toList[0];
    for (int i = 1; i < toList.size(); i++)
      out << "/" << toList[i];
    out << endl;
  }
}

void Translator::loadDictionaries() {
	m_dic.push_back(Dictionary()); m_dic.back().load("0.txt");
	m_dic.push_back(Dictionary()); m_dic.back().load("1.txt");
	m_dic.push_back(Dictionary()); m_dic.back().load("2.txt");
}

QString Translator::translateHtml(const QString& html)
{
	Tags tags;
	parseHtml(html, tags);
	for (int i = 0; i < tags.size(); i++) {
		Tag& tag = tags[i];
		if (tag.second) {
			//Log::m_log << "Translating: " << tag.first.toStdString() << endl;
			tag.first = translateText(tag.first);
		}
	}
	return tags.join();
}

QString Translator::translateText(const QString& text) 
{
	QString s;
	for (int i = 0; i < text.size(); ) {
		int j = i + 20;
		if (j > text.size()) j = text.size();
		for (; j > i; j--) {
			QString tmp = convert(text.mid(i, j-i));
			if (!tmp.isEmpty()) {
				s += tmp+" ";
				break;
			}
		}
		if (j == i) s += text[i];
		i = j > i ? j : i+1;
	}
	return s;
}

QString Translator::convert(const QString& text)
{
	QString to;
	for (int i = 0; i < m_dic.size(); i++) {
		if (m_dic[i].contains(text)) {
			to = m_dic[i].value(text)[0];
      //if (i == 0) to = makeName(to);
			break;
		}
	}
	//if (!to.isEmpty()) Log::m_log << "convert: " << text.toStdString() << " --> " << to.toStdString() << endl;
	return to;
}

QString Translator::makeName(const QString& text)
{
  QString ret = text;
  for (int i = 0; i < text.length(); i++)
    if ((i == 0 || QString(text[i-1]).trimmed().isEmpty()) && !QString(text[i]).trimmed().isEmpty()) 
      ret[i] = QString(text[i]).toUpper()[0];
  Log::m_log << "Name convert: " << text << " --> " << ret << endl;
  return ret;
}

void Translator::parseHtml(const QString& html, Tags& tags)
{
	int p = 0, q, r;
	QRegExp regexp("<[^>]*>");
	QStringList specialTags;
	specialTags << "script" << "style";

	while (p < html.length()) {
		q = html.indexOf(regexp, p);
		if (q == -1) break; // no tag found, the rest is text
		r = html.indexOf(">", q+1);
		QString tag;
		Q_FOREACH(const QString& s_tag, specialTags) {                // find a special tag
			if (html.mid(q+1, s_tag.length()).toLower() == s_tag) {
				tag = s_tag;
				break;
			}
		}
		if (!tag.isEmpty() && html.mid(r-1,1) != "/") {               // if found, find the corresponding closing tag
			r = html.indexOf("</" + tag + ">", q);
			if (r == -1) break;
			r += tag.length()+2;
		}
		if (q > p) tags << Tag(html.mid(p, q-p), 1);
		tags << Tag(html.mid(q, r-q+1), 0);
		//if (q > p) Log::m_log << "---Text--: " << html.mid(p, q-p).toStdString() << endl;
		//Log::m_log << "---Tag---: " << html.mid(q, r-q+1).toStdString() << endl;
		p = r+1;
	}
	if (p < html.length()) tags << Tag(html.mid(p), 1);
}

// ========== Translator ==============
Translator::Translator(WebBrowser* browser, const QString& html, const QUrl& url, QObject *parent) 
	: QThread(parent), m_html(html), m_url(url), m_browser(browser), m_id(m_lastID++)
{
	browser->m_tid = m_id;
}

Translator::~Translator()
{
  Log::m_log << "translator id=" << m_id << " deleted." << endl;
}

void Translator::run() 
{
	m_trHtml = translateHtml(m_html);
}
